package com.stm.bi.jdbc;

import com.stm.framework.core.util.SpringContextUtil;
import com.stm.framework.dbcp.DynamicDataSource;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import javax.sql.DataSource;

/**
 *
 * @Description TODO
 * @Author chenyingjun
 * @Date 2024/1/24 15:50
 * @Version 1.0
 **/
@Aspect
@Order(-Integer.MAX_VALUE) //这是为了保证AOP在事务注解之前生效,Order的值越小,优先级越高
@Component
public class DataSourceSwitchAspect {


    private static final Logger logger = LoggerFactory.getLogger(DataSourceSwitchAspect.class);

    @Around("@annotation(dataSourceSwitch)")
    public Object around(ProceedingJoinPoint joinPoint, DataSourceSwitch dataSourceSwitch) throws Throwable {
        boolean doSwitch = false;
        try {
            DataSource dataSource = SpringContextUtil.getBean(dataSourceSwitch.value().getDataSource());
            if(dataSource != null){
                logger.info(">>>>>>>>>>>线程"+Thread.currentThread().getName()+"绑定数据源【"+dataSourceSwitch.value().getDataSource()+"】<<<<<<<<<<<<");
                DynamicDataSource.switchDataSource(dataSource);
                doSwitch = true;
            }
            Object returnValue = joinPoint.proceed();
            return returnValue;
        }finally {
            if(doSwitch){
                DynamicDataSource.endSwitch();
                logger.info(">>>>>>>线程"+Thread.currentThread().getName()+"清除绑定数据源<<<<<<<<<<<<");
            }
        }
    }

    @Around("execution(* com.stm.framework.repository.BaseRepository.*(..))")
    public Object around1(ProceedingJoinPoint joinPoint) throws Throwable {
        return switchDataSource(joinPoint);
    }
    @Around("execution(* com.stm.bi.repository.*.*Repository.*(..))")
    public Object around2(ProceedingJoinPoint joinPoint) throws Throwable {
        return switchDataSource(joinPoint);
    }


    private Object switchDataSource(ProceedingJoinPoint joinPoint) throws Throwable {
        Object object = joinPoint.getTarget();
        boolean doSwitch = false;
        Package pkg = object.getClass().getPackage();
        if(pkg == null){
            return joinPoint.proceed();
        }
       String packageName = pkg.getName();
        DataSourceEnum dataSourceEnum = DataSourceEnum.getDataSourceEnum(packageName);
        if(dataSourceEnum != null){
            DataSource dataSource = SpringContextUtil.getBean(dataSourceEnum.getDataSource());
            if(dataSource != null){
                logger.info(">>>>>>>>>>>线程"+Thread.currentThread().getName()+"绑定数据源【"+dataSourceEnum.name()+"】<<<<<<<<<<<<");
                DynamicDataSource.switchDataSource(dataSource);
                doSwitch = true;
            }
        }
        try {
            return joinPoint.proceed();
        }finally {
            if(doSwitch){
                DynamicDataSource.endSwitch();
                logger.info(">>>>>>>线程"+Thread.currentThread().getName()+"清除绑定数据源<<<<<<<<<<<<");
            }
        }
    }
}
